home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / utils / nroff~06.zoo / strings.c < prev    next >
C/C++ Source or Header  |  1992-07-16  |  6KB  |  333 lines

  1. static char *rcsid_strings_c="$Id: strings.c,v 1.2 1992/07/16 10:38:32 rosenkra Exp $";
  2.  
  3. /*
  4.  * $Log: strings.c,v $
  5.  * Revision 1.2  1992/07/16  10:38:32  rosenkra
  6.  * port to gcc, add tm,ie,el
  7.  *
  8.  */
  9.  
  10. /*
  11.  *    strings.c - String input/output processing for nroff word processor
  12.  *
  13.  *    adapted for atariST/TOS by Bill Rosenkranz 11/89
  14.  *    net:    rosenkra@convex.com
  15.  *    CIS:    71460,17
  16.  *    GENIE:    W.ROSENKRANZ
  17.  *
  18.  *    original author:
  19.  *
  20.  *    Stephen L. Browning
  21.  *    5723 North Parker Avenue
  22.  *    Indianapolis, Indiana 46220
  23.  *
  24.  *    history:
  25.  *
  26.  *    - Originally written in BDS C;
  27.  *    - Adapted for standard C by W. N. Paul
  28.  *    - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
  29.  */
  30.  
  31. #undef NRO_MAIN                    /* extern globals */
  32.  
  33. #include <stdio.h>
  34. #include "nroff.h"
  35.  
  36.  
  37.  
  38. /*------------------------------*/
  39. /*    defstr            */
  40. /*------------------------------*/
  41. void defstr (p)
  42. REGISTER char  *p;
  43. {
  44.  
  45. /*
  46.  *    Define a string. top level, read from command line.
  47.  *
  48.  *    we should read string without interpretation EXCEPT:
  49.  *
  50.  *    1) number registers are interpolated
  51.  *    2) strings indicated by \* are interpolated
  52.  *    3) arguments indicated by \$ are interpolated
  53.  *    4) concealed newlines indicated by \(newline) are eliminated
  54.  *    5) comments indicated by \" are eliminated
  55.  *    6) \t and \a are interpreted as ASCII h tab and SOH.
  56.  *    7) \\ is interpreted as backslash and \. is interpreted as a period.
  57.  *
  58.  *    currently, we do only 3. a good place to do it would be here before
  59.  *    putstr, after colstr...
  60.  */
  61.  
  62.     REGISTER char  *q;
  63.     REGISTER int    i;
  64.     char        name[MNLEN];
  65.     char        defn[MXMLEN];
  66.  
  67.  
  68.  
  69.     name[0] = '\0';
  70.     defn[0] = '\0';
  71.  
  72.  
  73.     /*
  74.      *   skip the .ds and get to the name...
  75.      */
  76.     q = skipwd (p);
  77.     q = skipbl (q);
  78.  
  79.     /*
  80.      *   ok, name now holds the name. make sure it is valid (i.e. first
  81.      *   char is alpha...). getwrd returns the length of the word.
  82.      */
  83.     i = getwrd (q, name);
  84.     if (!name[0])
  85.     {
  86.         fprintf (err_stream,
  87.             "***%s: missing or illegal string definition name\n",
  88.             myname);
  89.         err_exit (-1);
  90.     }
  91.  
  92.     /*
  93.      *   truncate to 2 char max name.
  94.      */
  95.     if (i > 2)
  96.         name[2] = EOS;
  97.  
  98.  
  99.     /*
  100.      *   skip the name to get to the string. it CAN start with a " to
  101.      *   have leading blanks...
  102.      */
  103.     q = skipwd (q);
  104.     q = skipbl (q);
  105.  
  106.  
  107.  
  108.     /*
  109.      *   read rest of line from input stream and collect string into
  110.      *   temp buffer defn
  111.      */
  112.     if ((i = colstr (q, defn)) == ERR)
  113.     {
  114.         fprintf (err_stream,
  115.             "***%s: string definition too long\n", myname);
  116.         err_exit (-1);
  117.     }
  118.  
  119.  
  120.     /*
  121.      *   store the string
  122.      */
  123.     if (putstr (name, defn) == ERR)
  124.     {
  125.         fprintf (err_stream,
  126.             "***%s: string definition table full\n", myname);
  127.         err_exit (-1);
  128.     }
  129. }
  130.  
  131.  
  132.  
  133.  
  134.  
  135. /*------------------------------*/
  136. /*    colstr            */
  137. /*------------------------------*/
  138. int colstr (p, d)
  139. REGISTER char  *p;
  140. char           *d;
  141. {
  142.  
  143. /*
  144.  *    Collect string definition from input stream
  145.  */
  146.  
  147.     REGISTER int    i = 0;
  148.     char           *pstart = p;
  149.  
  150.  
  151.  
  152.     /*
  153.      *   if there is a " here, we have leading blanks (skipbl in caller
  154.      *   found it). just get past it...
  155.      */
  156.     if (*p == '\"')
  157.         p++;
  158.  
  159.  
  160.     while (*p != EOS)
  161.     {
  162.         /*
  163.          *   are we over the length limit for a single string?
  164.          */
  165.         if (i >= MXMLEN - 1)
  166.         {
  167.             d[i - 1] = EOS;
  168.             return (ERR);
  169.         }
  170.  
  171.         /*
  172.          *   "i break for comments..."
  173.          */
  174.         if (*p == '\\' && *(p+1) == '\"')
  175.         {
  176.             /*
  177.              *   first back over any whitespace between comment
  178.              *   start and last character in line. remember to
  179.              *   decrement counter i, too...
  180.              */
  181.             p--;
  182.             while (isspace (*p) && p > pstart && i > 0)
  183.             {
  184.                 p--;
  185.                 i--;
  186.             }
  187.  
  188.             /*
  189.              *   now skip over the comment until we reach the
  190.              *   trailing newline
  191.              */
  192.             while (*p != EOS)
  193.             {
  194.                 if (*p == '\n' || *p == '\r')
  195.                     break;
  196.                 p++;
  197.             }
  198.         }
  199.  
  200.         /*
  201.          *   stop at the newline...
  202.          */
  203.         if (*p == '\n' || *p == '\r')
  204.             break;
  205.  
  206.         /*
  207.          *   copy it
  208.          */
  209.         d[i++] = *p++;
  210.     }
  211.     d[i] = EOS;
  212.     return (i);
  213. }
  214.  
  215.  
  216.  
  217.  
  218.  
  219. /*------------------------------*/
  220. /*    putstr            */
  221. /*------------------------------*/
  222. int putstr (name, p)
  223. REGISTER char  *name;
  224. REGISTER char  *p;
  225. {
  226.  
  227. /*
  228.  *    Put string definition into (macro) table
  229.  *
  230.  *    NOTE: any expansions of things like number registers SHOULD
  231.  *    have been done already. strings and macros share mb buffer
  232.  */
  233.  
  234.  
  235.     /*
  236.      *   any room left? (did we exceed max number of possible macros)
  237.      */
  238.     if (mac.lastp >= MXMDEF)
  239.         return (ERR);
  240.  
  241.     /*
  242.      *   will new one fit in big buffer?
  243.      */
  244.     if (mac.emb + strlen (name) + strlen (p) + 1 > &mac.mb[MACBUF])
  245.     {
  246.         return (ERR);
  247.     }
  248.  
  249.  
  250.     /*
  251.      *   add it...
  252.      *
  253.      *   bump counter, set ptr to name, copy name, copy def.
  254.      *   finally increment end of macro buffer ptr (emb).
  255.      *
  256.      *   string looks like this in mb:
  257.      *
  258.      *    mac.mb[MACBUF]        size of total buf
  259.      *    lastp < MXMDEF        number of macros/strings possible
  260.      *    *mnames[MXMDEF]        -> names, each max length
  261.      *    ...______________________________...____________________...
  262.      *        / / /|X|X|0|string definition      |0| / / / / / / /
  263.      *    .../_/_/_|_|_|_|_________________...___|_|/_/_/_/_/_/_/_...
  264.      *            ^
  265.      *            |
  266.      *            \----- mac.mnames[mac.lastp] points here
  267.      *
  268.      *   both the 2 char name (XX) and the descripton are null term and
  269.      *   follow one after the other.
  270.      */
  271.     ++mac.lastp;
  272.     mac.mnames[mac.lastp] = mac.emb;
  273.     strcpy (mac.emb, name);
  274.     strcpy (mac.emb + strlen (name) + 1, p);
  275.     mac.emb += strlen (name) + strlen (p) + 2;
  276.     return (OK);
  277. }
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284. /*------------------------------*/
  285. /*    getstr            */
  286. /*------------------------------*/
  287. char *getstr (name)
  288. REGISTER char  *name;
  289. {
  290.  
  291. /*
  292.  *    Get (lookup) string definition from namespace
  293.  */
  294.  
  295.     REGISTER int    i;
  296.  
  297.     /*
  298.      *   loop for all macros, starting with last one
  299.      */
  300.     for (i = mac.lastp; i >= 0; --i)
  301.     {
  302.         /*
  303.          *   is this REALLY a macro?
  304.          */
  305.         if (mac.mnames[i])
  306.         {
  307.             /*
  308.              *   if it compares, return a ptr to it
  309.              */
  310.             if (!strcmp (name, mac.mnames[i]))
  311.             {
  312. /*!!!debug            puts (mac.mnames[i]);*/
  313.  
  314.                 if (mac.mnames[i][1] == EOS)
  315.                     return (mac.mnames[i] + 2);
  316.                 else
  317.                     return (mac.mnames[i] + 3);
  318.             }
  319.         }
  320.     }
  321.  
  322.     /*
  323.      *   none found, return null
  324.      */
  325.     return (NULL_CPTR);
  326. }
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.